/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package pt.mleiria.utils;

import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
import org.apache.log4j.Logger;

/**
 *
 * @author manuel
 */
public class AlphabetFreq {

    private static Logger LOG = Logger.getLogger(AlphabetFreq.class);
    private static final boolean isDebug = false;

    //private final String englishFreqFile = "englishFreq.csv";
    public static final double max = 12.702;
    public static final Map<Object, Number> EnglishFreq;
    public static final byte[] q = new byte[255];
    public static final byte[] p = new byte[255];
    public static final String[] alphabetLetters = new String[26];

    public AlphabetFreq() {
        //final InputOutputUtils iou = new InputOutputUtils();
        //EnglishFreq = iou.loadFreqFromCsv(englishFreqFile);
    }

    static {
        EnglishFreq = new TreeMap<Object, Number>();
        EnglishFreq.put('a', 8.167);
        EnglishFreq.put('b', 1.492);
        EnglishFreq.put('c', 2.782);
        EnglishFreq.put('d', 4.253);
        EnglishFreq.put('e', 12.702);
        EnglishFreq.put('f', 2.228);
        EnglishFreq.put('g', 2.015);
        EnglishFreq.put('h', 6.094);
        EnglishFreq.put('i', 6.966);
        EnglishFreq.put('j', 0.153);
        EnglishFreq.put('k', 0.772);
        EnglishFreq.put('l', 4.025);
        EnglishFreq.put('m', 2.406);
        EnglishFreq.put('n', 6.749);
        EnglishFreq.put('o', 7.507);
        EnglishFreq.put('p', 1.929);
        EnglishFreq.put('q', 0.095);
        EnglishFreq.put('r', 5.987);
        EnglishFreq.put('s', 6.327);
        EnglishFreq.put('t', 9.056);
        EnglishFreq.put('u', 2.758);
        EnglishFreq.put('v', 0.978);
        EnglishFreq.put('w', 2.360);
        EnglishFreq.put('x', 0.150);
        EnglishFreq.put('y', 1.974);
        EnglishFreq.put('z', 0.074);
        for (int i = 0; i < 255; i++) {
            p[i] = (byte) i;
        }
        for(int i = 97; i <= 122; i++){
            alphabetLetters[i-97] = String.valueOf((char)i).toUpperCase();
        }
    }

    public static Map<Integer, Double> getKeyLength(final String cipherText, boolean isHex) {

        Map<Integer, Double> icMap = new HashMap<Integer, Double>();
        byte[] cipher;
        if (isHex) {
            cipher = MathUtils.hexStringToByteArray(cipherText);
        } else {
            cipher = MathUtils.StringToBytesASCII(cipherText);
        }
        LOG.info("cipherText:" + cipherText);
        final int sampleUniverse = cipher.length;
        for (int i = 0; i < sampleUniverse; i++) {
            calculateIC(cipher, i + 2, icMap);
        }
        return icMap;
    }

    private static void calculateIC(byte[] cipher, int keyLength, Map<Integer, Double> icMap) {
        final StringBuffer sb = new StringBuffer();
        final Map<Byte, Integer> tmp = new HashMap<Byte, Integer>();
        for (int i = keyLength-1; i < cipher.length; i = i + keyLength) {
            sb.append((char) cipher[i]);
            if (tmp.containsKey(cipher[i])) {
                tmp.put(cipher[i], tmp.get(cipher[i]) + 1);
            } else {
                tmp.put(cipher[i], 1);
            }
        }
       // LOG.info("[Key;value]:[" + keyLength + ";" + sb.toString() + "]");
        if (!isDebug) {
            for (Map.Entry<Byte, Integer> entry : tmp.entrySet()) {
                LOG.info("Key : " + entry.getKey().intValue() + " Value : "
                        + entry.getValue());
            }
        }
        for (int i = 0; i < 255; i++) {
            if (tmp.containsKey(q[i])) {
                q[i] = tmp.get(q[i]).byteValue();
                q[i] = (byte) (q[i] / cipher.length);
            }
        }
        double result = 0;
        for (int i = 0; i < 255; i++) {
            result += q[i] * q[i];
        }
        icMap.put(keyLength, result);
    }

    public static void main(String[] args) {
        String cipherText = "vptnvffuntshtarptymjwzirappljmhhqvsubwlzzygvtyitarptyiougxiuydtgzhhvvmum"
                + "shwkzgstfmekvmpkswdgbilvjljmglmjfqwioiivknulvvfemioiemojtywdsajtwmtcgluy"
                + "sdsumfbieugmvalvxkjduetukatymvkqzhvqvgvptytjwwldyeevquhlulwpkt";
        Map<Integer, Double> icMap = getKeyLength(cipherText, false);

        if (isDebug) {
            for (Map.Entry<Integer, Double> entry : icMap.entrySet()) {
                LOG.info("Key : " + entry.getKey().intValue() + " Value : "
                        + entry.getValue());
            }
        }
    }
}
